package com.ls.quartz;

import com.ls.entity.DiscussPost;
import com.ls.service.DiscussPostService;
import com.ls.service.ElasticsearchService;
import com.ls.service.LikeService;
import com.ls.util.CommunityConstant;
import com.ls.util.RedisKeyUtil;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundSetOperations;
import org.springframework.data.redis.core.RedisTemplate;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Objects;

/**
 * @author ls
 * @version v1.0
 * @description
 * @date 2021/8/24 22:36
 */
public class PostScoreRefreshJob implements Job {

    private static final Logger logger = LoggerFactory.getLogger(PostScoreRefreshJob.class);

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private DiscussPostService discussPostService;

    @Autowired
    private LikeService likeService;

    @Autowired
    private ElasticsearchService elasticsearchService;

    /**
     * 牛客纪元
     */
    private static final Date EPOCH;

    static {
        try {
            EPOCH = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2014-08-01 00:00:00");
        } catch (ParseException e) {
            throw new RuntimeException("初始化牛客纪元失败!");
        }
    }

    @Override
    public void execute(JobExecutionContext context) throws JobExecutionException {
        String redisKey = RedisKeyUtil.getPostScoreKey();
        BoundSetOperations<String, Object> operations = redisTemplate.boundSetOps(redisKey);
        if (Objects.isNull(operations.size()) || Objects.equals(operations.size(), 0L)) {
            logger.info("[任务取消] 没有要刷新的帖子!");
            return;
        }
        logger.info("[任务开始] 正在刷新帖子分数: {} ", operations.size());
        while (operations.size().doubleValue() > 0) {
            this.refreshPostScore((int) operations.pop());
        }
        logger.info("[任务结束] 帖子分数刷新完毕!");
    }

    /**
     * 功能描述: <br>
     * 刷新帖子分数
     * 分数计算
     * log(精华分 + 评论数 * 10 + 点赞数 * 2 + 收藏数 * 2) + (发布时间 - 牛客纪元)
     *
     * @param postId
     * @author ls
     * @date 2021/8/24 23:19
     */
    private void refreshPostScore(int postId) {
        DiscussPost post = discussPostService.queryDiscussPostById(postId);
        if (post == null) {
            logger.error("该帖子不存在, id: {} ", postId);
            return;
        }
        // 是否加精
        boolean isWonderful = post.getStatus() == 1;
        // 评论数量
        int commentCount = post.getCommentCount();
        // 点赞数量
        long likeCount = likeService.getEntityLikeCount(CommunityConstant.ENTITY_TYPE_POST, postId);

        // 计算权重
        double w = (isWonderful ? 75 : 0) + commentCount * 10D + likeCount * 2;
        // 分数 = 权重 + 距离天数
        double score = Math.log10(Math.max(w, 1))
                + (post.getCreateTime().getTime() - EPOCH.getTime()) / (1000 * 60 * 60 * 24D);
        // 更新帖子分数
        discussPostService.updateScore(postId, score);
        // 同步elasticsearch数据
        post.setScore(score);
        elasticsearchService.saveDiscussPost(post);
    }
}
